

// 简单验证线程可以同步

#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>
#include <unistd.h>

#define NUM 5
int cnt = 1000;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void* threadRun(void* args)
{
    std::string name = static_cast<const char*>(args);
    while(true)
    {
        pthread_mutex_lock(&lock);

        // 等待是由于临界资源不满足 例如卖票票卖完了等待 等待发票之后临界资源满足了唤醒之后继续运行
        // 等待大多数情况下要对临界资源进行判断 也就是访问临界区资源 这里只是为了演示同步就没有判断 
        // 那么等待一定是在临界区内部等待 等待成功后休眠也是在临界区内部
        pthread_cond_wait(&cond, &lock); 
        // 为什么要传入一把锁 这里简单提及后面还会解释 
        // 此时线程等待 要在临界区休眠 那么因为之前是加了锁的 你休眠了 其他线程还要竞争锁 不能占着不用
        // 在休眠前释放锁 所以要传入锁这个参数
        std::cout << name << ':' << "计算" << cnt << std::endl;
        cnt++;
        pthread_mutex_unlock(&lock);
    }
    return nullptr;
}
int main()
{
    std::vector<pthread_t> tids;
    for(int i = 0; i < NUM; i++)
    {
        char name[64];
        snprintf(name, 64, "thread-%d", i);
        pthread_t tid = 0;
        int n = pthread_create(&tid, nullptr, threadRun, name);
        if(n != 0) 
            continue;
        // 到这里说明线程创建成功
        tids.push_back(tid);
        sleep(1);
    }
    
    sleep(3);
    // 唤醒等待线程
    while(true)
    {
        // // 一次唤醒一个线程
        // std::cout << "唤醒一个线程..." << std::endl;
        // pthread_cond_signal(&cond);
        // sleep(1);
        // 一次唤醒所有线程
        std::cout << "唤醒所有线程" << std::endl;
        pthread_cond_broadcast(&cond);
        sleep(1);
    }

    for(auto& tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    return 0;
}